package org.gwt.grin.client;

import java.util.HashMap;
import java.util.Map;

import org.gwt.grin.client.animator.AnimationClient;
import org.gwt.grin.client.animator.AnimationContext;
import org.gwt.grin.client.animator.AnimationEngine;
import org.gwt.grin.client.features.Group;
import org.gwt.grin.client.features.InterpolatedModel;
import org.gwt.grin.client.features.Translator;
import org.gwt.grin.client.input.MouseClickedEvent;
import org.gwt.grin.client.input.MouseMovedEvent;
import org.gwt.grin.client.ui.Scene;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.ui.AbsolutePanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class GRIN extends Director implements EntryPoint, AnimationContext,
		KeyDownHandler, KeyUpHandler, MouseMoveHandler, ClickHandler {

	interface MyShowBuilder extends ShowBuilder<GRIN, MyClientBundle> {
	}

	private static final MyShowBuilder myShowBuilder = GWT
			.create(MyShowBuilder.class);

	private AnimationEngine animationEngine;
	private Show show;
	private Scene rootContainer = new Scene();

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		show = myShowBuilder.buildShow(this);
		animationEngine = new AnimationEngine(this,
				new AnimationClient[] { show }, getRootContainer());
		animationEngine.start();
	}

	/**
	 * Return the root container for this application, with the size set to the
	 * desired size. TODO ...
	 * 
	 * @return
	 */
	protected AbsolutePanel getRootContainer() {
		return rootContainer = new Scene();
	}

	public void animationInitialize() {
		GWT.log("animationInitialize()...");
	}

	public void animationFinishInitialization() {
		GWT.log("animationFinishInitialization()...");
		show.activateSegment(getSegment("S:Segment0"));

		rootContainer.addKeyDownHandler(this);
		rootContainer.addKeyUpHandler(this);
		rootContainer.addMouseMoveHandler(this);
		rootContainer.addClickHandler(this);
	}

	@Override
	public void onKeyDown(KeyDownEvent event) {
		show.handleKeyPressed(event.getNativeKeyCode());
	}

	@Override
	public void onKeyUp(KeyUpEvent event) {
		show.handleKeyReleased(event.getNativeKeyCode());
	}

	@Override
	public void onMouseMove(MouseMoveEvent event) {
		final int x = event.getClientX();
		final int y = event.getClientY();
		MouseMovedEvent cmd = new MouseMovedEvent(show, x, y);
		show.runCommand(cmd);
	}

	@Override
	public void onClick(ClickEvent event) {
		final int x = event.getNativeEvent().getClientX();
		final int y = event.getNativeEvent().getClientY();
		MouseClickedEvent cmd = new MouseClickedEvent(show, x, y);
		show.runCommand(cmd);
	}

	@Override
	public void notifyDestroyed() {
		if (troopersGroup != null) {
			troopersGroup.resetVisibleParts(null);
		}
		if (troopers != null) {
			for (int i = 1; i < troopers.length; i++) {
				if (troopers[i].top != null) {
					troopers[i].top.destroyClonedSubgraph();
				}
			}
		}
	}

	public void sayHello(String msg) {
		System.out.println(msg);
	}

	private Group troopersGroup;
	private Trooper[] troopers;

	private static class Trooper {
		Feature top;
		InterpolatedModel pos;
	}

	public void initializeGame() {
		int[] trooperX = new int[] { 100, 150, 200, 250, 300, 350, 400, 450 };
		Trooper firstTrooper = new Trooper();
		firstTrooper.top = getFeature("F:Box.Translator");
		firstTrooper.pos = (InterpolatedModel) getFeature("F:Box.Pos");

		troopers = new Trooper[trooperX.length];
		troopers[0] = firstTrooper;
		for (int i = 1; i < troopers.length; i++) {
			Map<Feature, Feature> clones = new HashMap<Feature, Feature>();
			Trooper t = new Trooper();
			t.top = firstTrooper.top.cloneSubgraph(clones);
			t.pos = (InterpolatedModel) clones.get(firstTrooper.pos);
			troopers[i] = t;
		}
		Feature[] groupMembers = new Feature[troopers.length];
		for (int i = 0; i < troopers.length; i++) {
			troopers[i].pos.setField(Translator.X_FIELD, trooperX[i]);
			groupMembers[i] = troopers[i].top;
		}

		troopersGroup = (Group) getFeature("F:Boxes");
		troopersGroup.resetVisibleParts(groupMembers);
	}

}